/*
 * Debts Manager. Simple android application for managing debts.
 * Copyright (C) 2010 Maxim Manuylov
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/gpl-2.0.html>.
 */

package manuylov.maxim.dm.activity;

import android.app.Activity;
import android.app.Dialog;
import android.content.ContentResolver;
import android.content.Intent;
import android.content.SharedPreferences;
import android.database.Cursor;
import android.provider.Contacts;
import android.view.*;
import android.view.View.OnClickListener;
import android.widget.ArrayAdapter;
import android.widget.TextView;
import android.widget.Toast;
import manuylov.maxim.common.util.GenericProcessor;
import manuylov.maxim.common.util.IntentUtil;
import manuylov.maxim.dm.Constants;
import manuylov.maxim.dm.R;
import manuylov.maxim.dm.data.DataManager;
import manuylov.maxim.dm.view.ImprovedAutoCompleteTextEdit;

import java.util.*;

public abstract class BaseDMActivity extends Activity {
    protected int getIntOrFinish(final Intent intent, final String name) {
        final int defaultValue = Constants.NO_VALUE;
        final int value = intent.getIntExtra(name, defaultValue);
        if (value == defaultValue) {
            finish();
        }
        return value;
    }

    protected String getStringOrFinish(final Intent intent, final String name) {
        final String value = intent.getStringExtra(name);
        if (value == null) {
            finish();
        }
        return value;
    }

    protected SharedPreferences getApplicationPreferences() {
        return getSharedPreferences(Constants.PREFERENCES_FILE_NAME, MODE_PRIVATE);
    }

    @Override
    public boolean onCreateOptionsMenu(final Menu menu) {
        final MenuInflater inflater = getMenuInflater();
        inflater.inflate(R.menu.main_menu, menu);
        return super.onCreateOptionsMenu(menu);
    }

    protected void showSettingsMenuItem(final Menu menu) {
        final MenuItem settingsMenuItem = menu.findItem(R.id.settings_menu_item);
        settingsMenuItem.setVisible(true);
    }

    @Override
    public boolean onOptionsItemSelected(final MenuItem item) {
        switch (item.getItemId()) {
            case R.id.home_menu_item: {
                goToHome();
                return true;
            }

            case R.id.quit_menu_item: {
                chainFinish();
                return true;
            }

            case R.id.settings_menu_item: {
                final Intent intent = IntentUtil.prepareExplicitIntent(this, Constants.ACTION_CHANGE_SETTINGS, Settings.class);
                startActivityForResult(intent, Constants.REQUEST_DEFAULT);
                return true;
            }
        }
        return super.onOptionsItemSelected(item);
    }

    protected Dialog doCreateDialog(final int contentViewResId, final int titleResId, final DialogProcessor okButtonOnClickProcessor) {
        final Dialog dialog = new Dialog(this);
        dialog.setContentView(contentViewResId);
        dialog.setTitle(titleResId);
        dialog.setCanceledOnTouchOutside(true);
        dialog.findViewById(R.id.ok_button).setOnClickListener(new OnClickListener() {
            public void onClick(final View v) {
                okButtonOnClickProcessor.process(dialog);
            }
        });
        dialog.findViewById(R.id.cancel_button).setOnClickListener(new OnClickListener() {
            public void onClick(final View v) {
                dialog.cancel();
            }
        });
        return dialog;
    }

    protected static interface DialogProcessor extends GenericProcessor<Void, Dialog> {
    }

    protected List<String> getAllPersons(final DataManager dataManager) {
        final ContentResolver content = getContentResolver();
        final String[] projection = new String[]{Contacts.People.NAME};
        final Cursor cursor = content.query(Contacts.People.CONTENT_URI, projection, null, null, null);
        final SortedSet<String> allPeople = getContacts(cursor);
        allPeople.addAll(dataManager.getAllPersons());
        return new ArrayList<String>(allPeople);
    }

    protected void setAutoCompleteAdapter(final ImprovedAutoCompleteTextEdit editor, final List<String> list) {
        editor.setAdapter(new ArrayAdapter<String>(this, android.R.layout.simple_dropdown_item_1line, list));
    }

    private SortedSet<String> getContacts(final Cursor cursor) {
        final SortedSet<String> contacts = new TreeSet<String>(new Comparator<String>() {
            public int compare(final String object1, final String object2) {
                return object1.compareToIgnoreCase(object2);
            }
        });

        while (cursor.moveToNext()) {
            final String contact = cursor.getString(0);
            if (contact != null) {
                contacts.add(contact);
            }
        }

        return contacts;
    }

    protected String getTrimmedEditorText(final int editorId) {
        return doGetTrimmedEditorText(getWindow(), editorId);
    }

    protected String getTrimmedEditorText(final Dialog dialog, final int editorId) {
        return doGetTrimmedEditorText(dialog.getWindow(), editorId);
    }

    private String doGetTrimmedEditorText(final Window window, final int editorId) {
        final TextView textView = (TextView) getActualView(window.findViewById(editorId));
        final String text = textView.getText().toString();
        if (text.length() > 0) return trim(text);
        final CharSequence hint = textView.getHint();
        return hint == null ? "" : trim(hint.toString());
    }

    protected String trim(final String string) {
        final int length = string.length();
        int firstPos = 0;
        while (firstPos < length && string.charAt(firstPos) <= ' ') firstPos++;
        if (firstPos == length) return "";
        int lastPos = length - 1;
        while (string.charAt(lastPos) <= ' ') lastPos--;
        if (firstPos > 0 || lastPos < length - 1) {
            return string.substring(firstPos, lastPos + 1);
        } else {
            return string;
        }
    }

    protected void showShortToast(final int messageResId, final Object... formatArgs) {
        Toast.makeText(this, getResources().getString(messageResId, formatArgs), Toast.LENGTH_SHORT).show();
    }

    protected void focus(final int viewId) {
        doFocus(getWindow(), viewId);
    }

    protected void focus(final Dialog dialog, final int viewId) {
        doFocus(dialog.getWindow(), viewId);
    }

    protected void doFocus(final Window window, final int viewId) {
        getActualView(window.findViewById(viewId)).requestFocus();
    }

    protected View getActualView(final View view) {
        if (view instanceof ImprovedAutoCompleteTextEdit) {
            return ((ImprovedAutoCompleteTextEdit) view).asTextView();
        }
        return view;
    }

    protected Integer parseInteger(final String string) {
        try {
            return Integer.parseInt(string);
        }
        catch (final NumberFormatException e) {
            return null;
        }
    }

    protected void setTitle(final Intent intent) {
        setTitle(getIntOrFinish(intent, Constants.ACTIVITY_LABEL_TEXT));
    }

    @Override
    protected void onActivityResult(final int requestCode, final int resultCode, final Intent data) {
        switch (resultCode) {
            case Constants.RESULT_CHAIN_FINISH: {
                chainFinish();
                break;
            }

            case Constants.RESULT_GO_TO_HOME: {
                goToHome();
                break;
            }

            case Constants.RESULT_NEED_TO_RELOAD_DATA: {
                reloadData();
                break;
            }
        }
        super.onActivityResult(requestCode, resultCode, data);
    }

    protected void reloadData() {
    }

    protected void goToHome() {
        setResult(Constants.RESULT_GO_TO_HOME);
        finish();
    }

    private void chainFinish() {
        setResult(Constants.RESULT_CHAIN_FINISH);
        finish();
    }
}
